#!/usr/bin/python
# -*- coding: utf8 -*-

import os, sys
import random
import time

import cv2 as cv
import numpy as np
import pyautogui as gui
import pygetwindow as getwin
import pydirectinput as dtin

BASE_PATH = os.path.dirname(__file__)
IMAGES_DIR = "images"
BORDER_SIZE = 12
TITLE_BAR_HEIGHT = 52
MOUSE_DISTANCE_360_DEGREE = 1372
MOUSE_DISTANCE_90_DEGREE = int(MOUSE_DISTANCE_360_DEGREE/4)

# noinspection PyTypeChecker
GAME_WINDOW: getwin.Win32Window = None
coord_offset_x = 0
coord_offset_y = 0

def resolve_filepath(*paths):
    return os.path.join(BASE_PATH, *paths)

def load_image(directory, filename):
    image_path = resolve_filepath(IMAGES_DIR, directory, filename)
    return cv.imdecode(np.fromfile(image_path, dtype=np.uint8), cv.IMREAD_GRAYSCALE)

def img_matched(template, region, ct=0.7):
    screen = gui.screenshot(region=region)
    screen = cv.cvtColor(np.array(screen), cv.COLOR_BGR2GRAY)
    res = cv.matchTemplate(screen, template, cv.TM_CCOEFF_NORMED) 
    min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)
    confidence_threshold = ct
    if max_val > confidence_threshold:
        return True
    return False

def fetch_game_window():
    title_prefix = "二重螺旋"
    global  GAME_WINDOW, coord_offset_x, coord_offset_y
    wins = getwin.getWindowsWithTitle(title_prefix)
    for w in wins:
        if w.title.startswith(title_prefix):
            GAME_WINDOW = w
            # coord_offset_x = 0
            coord_offset_y = GAME_WINDOW.top
            return True
    return False

def precise_sleep(duration: float) -> None:
    """
    高精度等待函数（微秒级精度）
    :param duration: 等待时长（秒），支持小数（如 0.001 表示 1 毫秒）
    """
    start_time = time.perf_counter()  # 高精度起始时间
    end_time = start_time + duration  # 目标结束时间
    
    # 循环等待，直到达到目标时间（最后阶段空循环，避免 sleep 带来的延迟）
    while time.perf_counter() < end_time:
        # 前 90% 时间用 sleep 减少 CPU 占用，最后 10% 空循环保证精度
        remaining = end_time - time.perf_counter()
        if remaining > 1e-4:  # 剩余时间>100微秒时，用 sleep 释放 CPU
            time.sleep(remaining * 0.9)  # 只 sleep 剩余时间的 90%，避免过度休眠

def mouse_move_rel(x, y):
    dtin.moveRel(xOffset=x, yOffset=y, relative=True)

def turn_left():
    """向左转身90度"""
    mouse_move_rel(- MOUSE_DISTANCE_90_DEGREE, 0)

def turn_right():
    mouse_move_rel(MOUSE_DISTANCE_90_DEGREE, 0)
    """向右转身90度"""

def fly(count=1):
    for i in range(count):
        dtin.press('q')
        if count > 1:
            time.sleep(0.9)

def move_win_to_left_bottom():
    screen_width, screen_height = gui.size()
    move_y = screen_height - GAME_WINDOW.height - 70 # 70是任务栏高度
    GAME_WINDOW.moveTo(-10, move_y) # x坐标设置为0时，窗口离左边缘有段距离，为了让窗口截图紧贴左边缘，x坐标设置为-10

def click_button_in_win(top_left_x, top_left_y, bottom_right_x, bottom_right_y):
    dtin.moveTo(
        coord_offset_x + random.randint(top_left_x, bottom_right_x),
        coord_offset_y + random.randint(top_left_y, bottom_right_y))
    dtin.click()

def resize_win_to_correct_size():
    correct_width = 1280
    correct_height = 720
    resize_width = correct_width + BORDER_SIZE * 2
    resize_height = correct_height + BORDER_SIZE + TITLE_BAR_HEIGHT
    GAME_WINDOW.resizeTo(resize_width, resize_height)

def create_img_element_by_points(folder, filename, top_left_x, top_left_y, bottom_right_x, bottom_right_y):
    return ImgElement(folder, filename, top_left_x, top_left_y,
                      bottom_right_x - top_left_x, bottom_right_y - top_left_y)

class ImgElement:

    image = None
    match_region = None
    debug = False

    def __init__(self, folder, filename, left, top, width, height):
        self.image = load_image(folder, filename)
        self.match_region = (coord_offset_x + left, coord_offset_y + top, width, height)
    
    def matched(self):
        if self.debug:
            debug_filename = "Z:\\" + time.strftime(r"%Y%m%d_%H%M%S", time.localtime()) + ".png"
            gui.screenshot(debug_filename, region=self.match_region)
        return img_matched(self.image, self.match_region)
    
    def save_region(self, save_path):
        gui.screenshot(save_path, region=self.match_region)

    def wait_until_match(self, print_head, interval):
        head_printed = False
        while not self.matched():
            if not GAME_WINDOW.isActive:
                sys.exit(1)
            if head_printed:
                print('。', end='', flush=True)
            else:
                print(print_head, end='', flush=True)
                head_printed = True
            time.sleep(interval)
        print('')
